<?php
/**
 * PHPinChains Framework
 *
 * LICENSE
 *
 * This source file is subject to the PHPinChains BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://phpinchains.synflag.com/en/pub/license.php
 *
 * @category   PHPinChains
 * @package    phpinchains
 * @copyright  Copyright (c) 2005-2007 SynFlag Online Agentur - Germany
 * @license    http://phpinchains.synflag.com/en/pub/license.php PHPinChains BSD License
 * @since Date 22.12.2005
 */

m2import('phpinchains/SynchronizerToken.php');
m2import('phpinchains/ValidationErrors.php');

/**
 * An ActionForm is used to transfer data from the request to the action and from there to the view.
 * 
 * The third parameter of any action method is a reference to the actionform. It
 * contains the request parameters. Thus, it is possible to fake a call of an action
 * by preparing an ActionForm with parameters and than calling an action via 
 * WebAction::callAction() or WebAction::dispatch(). The ActionForm also is apssed to
 * the forwarded view, which may be called after the action returned. In a PSP 
 * the ActionForm builds the global scope. All parameters passed to the ActionForm
 * on it's way through the caller are available in the global scope.  
 * 
 * @category   PHPinChains
 * @package    phpinchains
 * @copyright  Copyright (c) 2005-2007 SynFlag Online Agentur - Germany
 * @license    http://phpinchains.synflag.com/en/pub/license.php PHPinChains BSD License
 */
class phpinchains_ActionForm implements ArrayAccess
{

    /**
     * Assoz. array with all the data stored in the ActionForm
     * @var array
     * @access private
     */
    var $container = array();
    
    /**
     * @param array $data Initial data of the ActionForm
     */
    function phpinchains_ActionForm($data = array())
    {
        $this->container = $data;
        // for use with xics cms
        $this->container['doc_id'] = (isset($GLOBALS['doc_id']))?$GLOBALS['doc_id']:null;
        $this->container['validationErrors'] = new phpinchains_ValidationErrors();
    }

    public function resetErrors () {
        unset($this->container['validationErrors']);
        $this->container['validationErrors'] = new phpinchains_ValidationErrors();
    }


    public function offsetSet($offset, $value) {
        //if (is_array($value)) $value = new self($value);
        if ($offset === null) { // don't forget this!
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }
    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }
    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }
    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }


    /**
     * Get the value with the given key name
     * 
     * @param name string Name of the key
     * @return mixed Value with given key
     */
    function get($name)
    {
    	if (!isset($this->container[$name]))
    	   return null;
        return $this->container[$name];
    }

    /**
     * Return a value and remove it from the action form
     * 
     * @param name string Name of the key
     * @return mixed Value with given key
     */
    function getAndRemove($name)
    {
    	if (!isset($this->container[$name]))
    	   return null;
        $return = $this->container[$name];
        unset($this->container[$name]);
        return $return;
    }

    /**
     * Short cut for getAndRemove
     * 
     * @param name string Name of the key
     * @return mixed Value with given key
     */
    function gar($name)
    {
        return $this->getAndRemove($name);
    }

    /**
     * Remove the value with the given key name from the action form
     * 
     * @param name string Name of the key
     */
    function remove($name)
    {
        unset($this->container[$name]);
    }

    /**
     * Output the value with the given key name
     * 
     * @param name string Name of the key
     */
    function out($name)
    {
        print $this->container[$name];
    }

    /**
     * Set a value with a name key
     * 
     * @param name string Key name
     * @param value mixed Value to store
     */
    function set($name, $value)
    {
        $this->container[$name] = $value;
    }
    
    /**
     * Get a value by reference (not needed for objects in php5)
     *
     * Example:
     * <code>
     *  $ref = & $af->getRef('name');
     * </code>
     *  
     * @param name string Key name
     */
    function & getRef($name)
    {
        return $this->container[$name];
    }

    /**
     * Set a value by reference (not needed for objects in php5)
     * 
     * @param name string Key name
     * @param value mixed Value to store
     */
    function setRef($name, & $value)
    {
        $this->container[$name] = & $value;
    }
    
    /**
     * Creates an url with query string from an assoz array
     * 
     * Do NOT use with ActionDispatcherFilter!
     * 
     * @param params array Assoz array with name value pairs
     * @param addDocId bool Only used with XICS CMS
     */
    function url($params, $addDocId = true)
    {
        $qs = "";
        if ($addDocId)
            $qs = "doc_id=".$GLOBALS['doc_id'];
        if (count($params)) 
        {
            $qs .= '&';
            list($n, $v) = array_pop($params);
            $qs .= $n.'='.$v; 
            foreach ($params as $n => $v)
                $qs .= "&".$n."=".urlencode($v);
        }
        $url = $GLOBALS['env']->getServer('SCRIPT_NAME');
        $url .= ($qs)?'?'.$qs:''; 
        print $url;
    }
    
    /**
     * Only used with XICS CMS
     */
    function getDocId()
    {
        return $GLOBALS['doc_id'];
    }
    
    /**
     * Only used with XICS CMS
     */
    function getDocIdHidden()
    {
        return '<input type="hidden" name="doc_id" value="'.$GLOBALS['doc_id'].'"/>';
    }
    
    /**
     * Only used with XICS CMS
     */
    function docId()
    {
        print '<input type="hidden" name="doc_id" value="'.$GLOBALS['doc_id'].'"/>';
    }
    
    /**
     * Get the synchronizer token value (Only usable with single frame apps)
     * 
     * @return string Value of sync token
     */
    function syncToken($name = '')
    {
        $st = phpinchains_SynchronizerToken::getInstance($name);
        return $st->getToken();
    }
    
    /**
     * Get the synchronizer token field name (Only usable with single frame apps)
     * 
     * @return string Name of sync token
     */
    function syncTokenName($name = '')
    {
        $st = phpinchains_SynchronizerToken::getInstance($name);
        return $st->getName();
    }
    
    /**
     * Get the synchronizer token hidden field (Only usable with single frame apps)
     * 
     * @return string Hidden field html code
     */
    function syncTokenHidden($name = '')
    {
        $st = phpinchains_SynchronizerToken::getInstance($name);
        return $st->getHidden();
    }
    
    /**
     * Get the keys of the assoz container array
     * 
     * @return array Array with keys of assoz container array
     */
    function keys()
    {
        return array_keys($this->container);
    }
    
    /**
     * Get the internal container assoz array
     * 
     * @return array Assoz container array
     */
    function getArray()
    {
        return $this->container;
    }
    
    /**
     * Merge given array with container array of the ActionForm instance
     * 
     * @param container array Array to merge with container array
     */
    function setArray($container)
    {
        if (is_array($container))
            $this->container = array_merge($this->container, $container);
    }
    
    /**
     * Count the length of the container array
     * 
     * @return int Count of container array
     */
    function count()
    {
        return count($this->container);
    }
    
    /**
     * Clear contents
     */
    function clear()
    {
        $this->container = array();
    }
    
    /**
     * Dumps to string in query string format
     * 
     * @return string Dump string
     */
    function dumpNameValue ()
    {
        $out = array();
        foreach ($this->container as $n => $v)
            $out[] = $n.'='.$v;
        return join('&', $out);
    }

}

?>